added Feb 2001 SDK
[windows-sources.git] / shared source / vb / language / shared / dynamicarray.h
blobd4d309c085c4f4972dee420dee2923f798aea3fa
1 //-------------------------------------------------------------------------------------------------
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // A simple template that implements a dynamically sized
6 // array using memory from the heap.
7 //
8 //-------------------------------------------------------------------------------------------------
10 #pragma once
12 template<class TYPE>
13 class DynamicArray
15 public:
16 NEW_CTOR_SAFE()
18 // Make sure we're zeroed.
19 DynamicArray()
21 memset(this, 0, sizeof(*this));
24 // Makes sure that this goes away.
25 ~DynamicArray()
27 Destroy();
30 // Set the initial size of the array.
31 void SizeArray(_In_ unsigned long ulSlots)
33 Destroy();
35 m_array = VBAllocator::AllocateArray<TYPE>(ulSlots);
36 m_cEntries = 0;
37 m_cSlots = ulSlots;
40 // Copy the contents of one array into another.
41 void TransferFromArgument(DynamicArray<TYPE> *pda)
43 Destroy();
45 m_cSlots = pda->m_cSlots;
46 m_cEntries = pda->m_cEntries;
47 m_array = pda->m_array;
49 pda->m_cSlots = 0;
50 pda->m_cEntries = 0;
51 pda->m_array = NULL;
54 // Destroys the array.
55 void Destroy()
57 // Free the contents.
58 for (unsigned i = 0; i < m_cEntries; i++)
60 // This will cause the contents of our thinggy to get
61 // destroyed. Neato, eh?
63 // Note ([....]): The destructor will not get called if the object you are storing
64 // in the array is a pointer, so you will have to remove every element yourself
65 // and call delete on it.
67 //
70 m_array[i].~TYPE();
73 // Free the array.
74 if (m_array)
76 VBFree(m_array);
79 // Reset the members.
80 memset(this, 0, sizeof(DynamicArray<TYPE>));
83 // Resets the array without destroying any of its elements
84 // (good to use if the elements stored in the array are pointers).
85 void Collapse()
87 // Free the array.
88 if (m_array)
90 VBFree(m_array);
93 // Reset the members.
94 memset(this, 0, sizeof(DynamicArray<TYPE>));
97 // Resets the array so it has no size.
98 void Reset()
100 Shrink(m_cEntries);
104 // Manipulation methods.
107 // Get the number of entries in the array.
108 ULONG Count()
110 return m_cEntries;
113 // Get the array.
114 TYPE *Array()
116 return m_array;
119 // Get an element of an array.
120 TYPE &Element(unsigned iElement)
122 VSASSERT(iElement < m_cEntries, "Out of range.");
124 return m_array[iElement];
127 // Grow the size of the array. Returns the first element that
128 // was added.
130 TYPE &Grow(ULONG cGrow = 1)
132 VSASSERT(cGrow > 0, "Must be greater than 0");
134 if (m_cEntries + cGrow > m_cSlots)
137 // Expand the array.
138 ULONG cExpand = m_cSlots > cGrow ? m_cSlots : cGrow;
140 TYPE *rgt = (TYPE *)VBRealloc(
141 m_array,
142 VBMath::Multiply(
143 VBMath::Add(m_cSlots, cExpand),
144 sizeof(TYPE)));
146 // Zero the expanded array.
147 memset(rgt + m_cSlots, 0, cExpand * sizeof(TYPE));
149 // Set the new memory.
150 m_cSlots += cExpand;
151 m_array = rgt;
154 // Get the element that was added.
155 unsigned cFirst = m_cEntries;
157 // Grow the number of slots used.
158 m_cEntries += cGrow;
160 // Return the first element that was added.
161 return m_array[cFirst];
164 // Add an element to the end of the array.
166 void AddElement( const TYPE& ElementToAdd )
168 TYPE& NewElement = Grow();
169 NewElement = ElementToAdd;
172 // Shrink the array.
173 void Shrink(ULONG cShrink = 1)
175 VSASSERT(m_cEntries >= cShrink, "Underflow.");
177 for (unsigned i = m_cEntries; i > m_cEntries - cShrink; )
180 i--;
182 // This will cause the contents of our thinggy to get
183 // destroyed. Neato, eh?
190 m_array[i].~TYPE();
193 memset(m_array + m_cEntries - cShrink, 0, sizeof(TYPE) * cShrink);
194 m_cEntries -= cShrink;
197 // Add an element to the array.
198 TYPE &Add(ULONG cAdd = 1)
200 return Grow(cAdd);
203 // Add element to the array and invoke the constructor properly.
204 TYPE &CreateNew(ULONG cAdd = 1)
206 TYPE &rFirst = Grow(cAdd);
207 for (ULONG i = 0; i < cAdd; ++i)
209 new((void*)(&rFirst + i)) TYPE();
211 return rFirst;
214 // Remove an element from the array, even from the middle.
215 void Remove(ULONG iRemove)
217 VSASSERT(iRemove < m_cEntries, "Index out of range.");
219 // Destroy the element.
221 m_array[iRemove].~TYPE();
224 // Copy the entries that appear after this one.
225 memmove(m_array + iRemove,
226 m_array + iRemove + 1,
227 (m_cEntries - iRemove - 1) * sizeof(TYPE));
229 // Manually remove the last element.
230 m_cEntries--;
232 memset(m_array + m_cEntries, 0, sizeof(TYPE));
235 //. Insert an element into the array, even into the middle.
236 TYPE &Insert(ULONG index)
238 VSASSERT(index <= m_cEntries, "Index out of range.");
239 Grow(); // grow by 1 slot.
241 // Move all the entries that appear after this one back one slot.
242 // If some regions of the source area and the destination overlap, memmove ensures that the original source bytes in the overlapping region are copied before being overwritten.
243 memmove(m_array + index + 1,
244 m_array + index,
245 (m_cEntries - index - 1) * sizeof(TYPE));
247 // Clean the slot
248 memset(m_array + index, 0, sizeof(TYPE));
250 // Return the element.
251 return m_array[index];
254 // Copies the array element in fromIndex over the array element in toIndex and then
255 // removes the element at fromIndex.
256 void CopyOver(ULONG toIndex, ULONG fromIndex)
258 VSASSERT(toIndex <= m_cEntries && fromIndex <= m_cEntries, "Index out of range.");
260 // Nothing to do if we are copying from and to the same index.
261 if (toIndex == fromIndex)
263 return;
266 memcpy(m_array + toIndex, m_array + fromIndex, sizeof(TYPE));
267 Remove(fromIndex);
270 // Return the last slot in the array.
271 TYPE &End()
273 return m_array[m_cEntries - 1];
276 private:
278 ULONG m_cSlots;
279 ULONG m_cEntries;
281 TYPE *m_array;